home *** CD-ROM | disk | FTP | other *** search
- /* -> c.ckafio
- */
-
- char *ckzv = "Arthur file support, 25 June 87";
-
- /* C K A F I O -- Kermit file system support for Arthur */
-
- /*
- Author: Frank da Cruz (SY.FDC@CU20B),
- Columbia University Center for Computing Activities, January 1985.
- Copyright (C) 1985, Trustees of Columbia University in the City of New York.
- Permission is granted to any individual or institution to use, copy, or
- redistribute this software so long as it is not sold for profit,
- provided this copyright notice is retained.
- Arthur version: Graham Toal/Acorn VLSI Tools Group (c) Acorn Computers Plc.
- */
-
- /* Includes */
-
- #include "ckcker.h" /* Kermit definitions */
- #include "ckcdeb.h" /* Typedefs, debug formats, etc */
- #include <stdio.h> /* Standard i/o */
- #ifdef PANOS
- #include <ascii.h>
- #endif
- #ifdef ANSI
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include "h.ckuusr"
- #include "h.ckafio"
- #include "h.ckamis"
- #endif
- #ifdef ARTHUR
- #include "h.plib"
- #include "h.dir"
- #endif
- #define NL LF
-
- char *ckzsys = " Acorn Arthur";
-
- /* Definitions of some Arthur system commands - needs changing */
-
- char *DIRCMD = "cat "; /* For directory listing */
- char *DELCMD = "delete "; /* For file deletion */
- char *TYPCMD = "type "; /* For typing a file */
- char *PWDCMD = "pwd "; /* For saying where I am */
- char *CWDCMD = "dir "; /* For selecting new dir */
-
- char *SPACMD = "run du "; /* Space/quota of current directory */
- char *SPACM2 = "run du "; /* For space in specified directory */
- char *WHOCMD = "users "; /* For seeing who's logged in */
-
- /*
- Functions (n is one of the predefined file numbers from ckermi.h):
-
- zopeni(n,name) -- Opens an existing file for input.
- zopeno(n,name) -- Opens a new file for output.
- zclose(n) -- Closes a file.
- zchin(n,&c) -- Gets the next character from an input file.
- zsout(n,s) -- Write a null-terminated string to output file,
- buffered.
- zsoutl(n,s) -- Like zsout, but appends a line terminator.
- zsoutx(n,s,x) -- Write x characters to output file, unbuffered.
- zchout(n,c) -- Add a character to an output file, unbuffered.
- zchki(name) -- Check if named file exists and is readable,
- return size.
- zchko(name) -- Check if named file can be created.
- znewn(name,s) -- Make a new unique file name based on the given name.
- zdelet(name) -- Delete the named file.
- zxpand(string) -- Expands the given wildcard string into a list of files.
- znext(string) -- Returns the next file from the list in "string".
- zxcmd(cmd) -- Execute the command in a lower fork.
- zclosf() -- Close input file associated with zxcmd()'s lower fork.
- zrtol(n1,n2) -- Convert remote filename into local form.
- zltor(n1,n2) -- Convert local filename into remote form.
- zchdir(dirnam) -- Change working directory.
- zhome() -- Return pointer to home directory name string.
- zkself() -- Kill self, log out own job.
- */
-
- /* Declarations */
- #define NOFILE -99
-
- int fp[ZNFILS] = { NOFILE, NOFILE, NOFILE, NOFILE, NOFILE, NOFILE, NOFILE,
- NOFILE, NOFILE };
- int isout[ZNFILS]= { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
- #ifdef PANOS
- extern int GetFileInformation () asm;
- extern int EndOfFile() asm;
- extern int SWriteByte() asm;
- extern int XSWriteByte() asm;
- extern int SBlockWrite() asm;
- extern int XSBlockWrite() asm;
- extern int SReadByte() asm;
- extern int XSReadByte() asm;
- extern int BytesOutstanding() asm;
- extern int XBytesOutstanding() asm;
- extern int XFindInput() asm;
- extern int XFindOutput() asm;
- extern int XCloseStream() asm;
- extern int XSFlushOutput() asm;
- #endif
-
- #define ZOBUFSIZ 4096
-
- static char zobuf[ZOBUFSIZ];
- int zohandle = NOFILE, zosize = 0;
-
- #ifdef ANSI
- void
- #endif
- Buffer(stream) int stream; /* select this stream to be buffered */
- {
- #ifdef ANSI
- extern void BFlush( int );
- #endif
-
- if (zohandle != NOFILE) BFlush(zohandle);
- zohandle = stream; zosize = 0;
- }
-
- #ifdef ANSI
- void
- #endif
- BFlush(stream) int stream; {
- if (stream == zohandle) {
- if (zosize) { XSBlockWrite(stream, zosize, zobuf); zosize = 0; }
- }
- XSFlushOutput(stream);
- }
-
- #ifdef ANSI
- void
- #endif
- BWrite(stream, num, data) int stream, num; char *data;
- {
- if (stream == zohandle) {
- while (num--) {
- zobuf[zosize++] = *data++;
- if (zosize >= ZOBUFSIZ) BFlush(stream);
- }
- }
- else XSBlockWrite(stream, num, data);
- }
-
- /***************************************************************/
- /* Z K S E L F -- Kill Self: log out own job, if possible. */
- /***************************************************************/
-
- #ifdef ANSI
- int
- #endif
- zkself() { return(0); }
-
- /******************************************************/
- /* Z O P E N I -- Open an existing file for input. */
- /******************************************************/
-
- #ifdef ANSI
- int
- #endif
- zopeni(n,name) int n; char *name; {
- debug(F111," zopeni",name,n);
- debug(F101," fp","", fp[n]);
- if (chkfn(n) != 0) return(0);
- isout[n] = 0;
- if (n == ZSYSFN) { /* Input from a system function? */
- debug(F110," invoking zxcmd",name,0);
- return(zxcmd(name)); /* Try to fork the command */
- }
- if (n == ZSTDIO) { /* Standard input? */
- /* no easy way to check in Arthur ?
- if (isatty(0)) { ermsg("Terminal input not allowed"); return(0); }
- */
- fp[ZIFILE] = XFindInput("INPUT:", 6); return(1);
- }
- fp[n] = XFindInput(name, strlen(name)); isout[n] = 0;
- debug(F111," zopeni", name, fp[n]);
- if (fp[n] < 0) { perror("zopeni"); fp[n] = NOFILE; }
- return(1);
- }
-
- /**************************************************/
- /* Z O P E N O -- Open a new file for output. */
- /**************************************************/
-
- #ifdef ANSI
- int
- #endif
- zopeno(n,name) int n; char *name; {
- if (chkfn(n)) return(0);
- isout[n] = 1;
- if (n == ZCTERM) { fp[ZOFILE] = XFindOutput("VDU:", 4); return(1); }
- if (n == ZSTDIO) { fp[ZOFILE] = XFindOutput("OUTPUT:", 7); return(1); }
- fp[n] = XFindOutput(name, strlen(name));
- if (n == ZOFILE) Buffer(fp[n]);
- if (fp[n] < 0) { perror("zopeno can't open"); fp[n] = NOFILE; }
- return((fp[n] >= 0) ? 1 : 0);
- }
-
- /********************************************/
- /* Z C L O S E -- Close the given file. */
- /********************************************/
-
- #ifdef ANSI
- int
- #endif
- zclose(n) int n; {
- if (chkfn(n) < 1) return(0); /* Check range of n */
- if ((n == ZIFILE) && (fp[ZSYSFN] >= 0) ) { zclosf(); return(1); }
- if (fp[n] >= 0) {
- if (isout[n]) { BFlush(fp[n]); }
- XCloseStream(fp[n]);
- }
- fp[n] = NOFILE; isout[n] = 0; return(1);
- }
-
- /************************************************************************/
- /* Z C H I N -- Get a character from the input file. */
- /* Returns -1 if EOF, 0 otherwise with character returned in argument */
- /************************************************************************/
-
- #ifdef ANSI
- int
- #endif
- zchin(n,c) int n; char *c;
- { int a;
- if (chkfn(n) < 1) return(-1);
- if (EndOfFile(fp[n]) == 1) return(-1);
- a = SReadByte(fp[n]);
- if (a < 0) return(-1);
- *c = a & 0377;
- return(0);
- }
-
- /****************************************************************/
- /* Z S O U T -- Write a string to the given file, buffered. */
- /****************************************************************/
-
- #ifdef ANSI
- int
- #endif
- zsout(n,s) int n; char *s; {
- if (chkfn(n) < 1) return(-1);
- BWrite(fp[n], strlen(s), s); return(0);
- }
-
- /***************************************************************************/
- /* Z S O U T L -- Write string to file, with line terminator, buffered */
- /***************************************************************************/
-
- #ifdef ANSI
- int
- #endif
- zsoutl(n,s) int n; char *s; {
- if (chkfn(n) < 1) return(-1);
- zsout(n,s); zchout(n,NL); return(0);
- }
-
- /**************************************************************/
- /* Z S O U T X -- Write x characters to file, unbuffered. */
- /**************************************************************/
-
- #ifdef ANSI
- int
- #endif
- zsoutx(n,s,x) int n, x; char *s; {
- BWrite(fp[n], x, s); BFlush(fp[n]); return(0);
- }
-
- /***************************************************************************/
- /* Z C H O U T -- Add a character to the given file. */
- /* Should return 0 or greater on success, -1 on failure (e.g. disk full) */
- /***************************************************************************/
-
- #ifdef ANSI
- int
- #endif
- zchout(
- #ifdef ANSI
- int n, char c)
- #else
- n,c) int n; char c;
- #endif
- {
- BWrite(fp[n], 1, &c); return(0);
- }
-
- /******************************************************************/
- /* C H K F N -- Internal function to verify file number is ok */
- /* */
- /* Returns: */
- /* -1: File number n is out of range */
- /* 0: n is in range, but file is not open */
- /* 1: n in range and file is open */
- /******************************************************************/
-
- #ifdef ANSI
- int
- #endif
- chkfn(n) int n; {
- switch (n) {
- case ZCTERM:
- case ZSTDIO:
- case ZIFILE:
- case ZOFILE:
- case ZDFILE:
- case ZTFILE:
- case ZPFILE:
- case ZSFILE:
- case ZSYSFN: break;
- default:
- debug(F101,"chkfn: file number out of range","",n);
- return(-1);
- }
- return( (fp[n] == NOFILE) ? 0 : 1 );
- }
-
- /************************************************************************/
- /* Z C H K I -- Check if input file exists and is readable */
- /* */
- /* Returns: */
- /* >= 0 if the file can be read (returns the size). */
- /* -1 if file doesn't exist or can't be accessed, */
- /* -2 if file exists but is not readable (e.g. a directory file). */
- /* -3 if file exists but protected against read access. */
- /* */
- /* */
- /* For Berkeley Unix, a file must be of type "regular" to be readable. */
- /* Directory files, special files, and symbolic links are not readable. */
- /************************************************************************/
-
- #ifndef ANSI
- struct FileData {int loadaddr, execaddr, length, attrib;};
-
- struct BTim {int low, high;};
- #endif
-
- long zchki(name) char *name; {
- struct FileData fileinfo;
- struct BTim timeinfo;
- int rc;
- fileinfo.length = -1;
- rc = GetFileInformation(&fileinfo, &timeinfo, name, strlen(name));
- if (rc == 2) return(-2);
- if (rc < 0) return(-1);
- return(fileinfo.length);
- }
-
- /****************************************************************************/
- /* Z C H K O -- Check if output file can be created */
- /* */
- /* Returns -1 if write permission for the file would be denied, 0 otherwise.*/
- /****************************************************************************/
-
- #ifdef ANSI
- int
- #endif
- zchko(name) char *name; { return(0); }
-
- /*********************************************/
- /* Z D E L E T -- Delete the named file. */
- /*********************************************/
-
- #ifdef ANSI
- int
- #endif
- zdelet(name) char *name; {
- char cmdstr [512];
- char *prefix, *suffix;
- char *cp;
- prefix = DELCMD; suffix = name;
- if (prefix == NULL || *prefix == '\0') return(0);
- for (cp = cmdstr; *prefix != '\0'; *cp++ = *prefix++) ;
- #ifdef ANSI
- while ( (*cp++ = *suffix++) != '\0' ) ;
- #else
- while (*cp++ = *suffix++) ;
- #endif
- system(cmdstr);
- return(1);
- }
-
- #ifdef PANOS
- /*******************************************************************/
- /* Z R T O L -- Convert remote filename into local form */
- /* For Arthur, this means changing dots into dashes. */
- /*******************************************************************/
-
- #ifdef ANSI
- static void
- #endif
- editfname(s,oldc,newc,newlast) char *s; char oldc,newc,newlast;
- /* changes occurrences of oldc in string s to newc, except for */
- /* last occurrence which gets changed to newlast */
- { char *p,*pos;
- pos = 0;
- for (p = s; *p; ++p) if (*p == oldc) { *p = newc; pos = p; }
- if (pos) *pos = newlast;
- }
-
- #ifdef ANSI
- void
- #endif
- zrtol(remote,local) char *remote,*local;
- { char *ans = local;
- #ifdef ANSI
- while ( (*local++ = *remote++) != '\0' );
- #else
- while (*local++ = *remote++);
- #endif
- editfname(ans, '-', '=', '=');
- editfname(ans, '.', '_', '-');
- editfname(ans, '/', '.', '.');
- }
-
- /*****************************************************************/
- /* Z L T O R -- Local TO Remote */
- /* Convert filename from local format to common (remote) form. */
- /*****************************************************************/
-
- #ifdef ANSI
- void
- #endif
- zltor(local,remote) char *local, *remote;
- { char *ans = remote;
- #ifdef ANSI
- while ( (*remote++ = *local++) != '\0' );
- #else
- while (*remote++ = *local++);
- #endif
- editfname(ans, '/', '=', '=');
- editfname(ans, '.', '/', '/');
- editfname(ans, '-', '-', '.');
- }
- #endif
-
-
- #ifdef ARTHUR
- /*******************************************************************/
- /* Z R T O L -- Convert remote filename into local form */
- /* For Arthur, this means changing dots into dashes. */
- /*******************************************************************/
-
- #ifdef ANSI
- static void
- #endif
- editfname(s,oldc,newc,newlast) char *s; char oldc,newc,newlast;
- /* changes occurrences of oldc in string s to newc, except for */
- /* last occurrence which gets changed to newlast */
- { char *p,*pos;
- pos = 0;
- for (p = s; *p; ++p) if (*p == oldc) { *p = newc; pos = p; }
- if (pos) *pos = newlast;
- }
-
- #ifdef ANSI
- void
- #endif
- zrtol(remote,local) char *remote,*local;
- { char *ans = local;
- #ifdef ANSI
- while ( (*local++ = *remote++) != '\0' );
- #else
- while (*local++ = *remote++);
- #endif
- editfname(ans, '-', '=', '=');
- editfname(ans, '.', '_', '-');
- editfname(ans, '/', '.', '.');
- }
-
- /*****************************************************************/
- /* Z L T O R -- Local TO Remote */
- /* Convert filename from local format to common (remote) form. */
- /*****************************************************************/
-
- #ifdef ANSI
- void
- #endif
- zltor(local,remote) char *local, *remote;
- { char *ans = remote;
- #ifdef ANSI
- while ( (*remote++ = *local++) != '\0' );
- #else
- while (*remote++ = *local++);
- #endif
- editfname(ans, '/', '=', '=');
- editfname(ans, '.', '/', '/');
- editfname(ans, '-', '-', '.');
- }
- #endif
-
- /***************************************/
- /* Z C H D I R -- Change directory */
- /***************************************/
-
- #ifdef ANSI
- int
- #endif
- zchdir(dirnam) char *dirnam; {
- char cmdstr [512];
- char *prefix, *suffix;
- char *cp;
- prefix = CWDCMD; suffix = dirnam;
- if (prefix == NULL || *prefix == '\0') return(0);
- for (cp = cmdstr; *prefix != '\0'; *cp++ = *prefix++) ;
- #ifdef ANSI
- while ( (*cp++ = *suffix++) != '\0' ) ;
- #else
- while (*cp++ = *suffix++) ;
- #endif
- system(cmdstr);
- return(1);
- }
-
- /************************************************************/
- /* Z H O M E -- Return pointer to user's home directory */
- /************************************************************/
- static char *myhome = "&";
- char *zhome() { return(myhome); }
-
- /****************************************************************************/
- /* Z X C M D -- Run a system command so its output can be read like a file */
- /****************************************************************************/
-
- #ifdef ANSI
- int
- #endif
- zxcmd(comand) char *comand; {
- char *redirect = "{ > kerm-tmp }";
- char cmdstr [512];
- char *prefix, *suffix;
- char *cp;
- prefix = comand; suffix = redirect;
- if (prefix == NULL || *prefix == '\0') return(0);
-
- for (cp = cmdstr; *prefix != '\0'; *cp++ = *prefix++) ;
-
- #ifdef ANSI
- while ( (*cp++ = *suffix++) != '\0' ) ;
- #else
- while (*cp++ = *suffix++) ;
- #endif
-
- fp[ZSYSFN] = XFindOutput("kerm-tmp", 8);
- XCloseStream(fp[ZSYSFN]); fp[ZSYSFN] = NOFILE;
- /* ensure it is empty in case not written to! */
-
- if( (strncmp(comand,SPACMD,strlen(SPACMD))==0) ||
- (strncmp(comand,SPACM2,strlen(SPACM2))==0) )
- du("kerm-tmp");
- else
- system(cmdstr);
-
-
- fp[ZIFILE] = fp[ZSYSFN] = XFindInput("kerm-tmp", 8);
- return(1);
- }
-
- /****************************************************************************/
- /* Z C L O S F - wait for the child fork to terminate and close the pipe. */
- /****************************************************************************/
-
- #ifdef ANSI
- int
- #endif
- zclosf() {
- if (fp[ZSYSFN] >= 0) XCloseStream(fp[ZSYSFN]);
- fp[ZIFILE] = fp[ZSYSFN] = NOFILE;
- return(1);
- }
-
- /****************************************************************************/
- /* Z X P A N D -- Expand a wildcard string into an array of strings */
- /* */
- /* Returns the number of files that match fn1, with data structures set up */
- /* so that first file (if any) will be returned by the next znext() call. */
- /****************************************************************************/
-
- #ifdef PANOS
- static int countwild, bfptr;
- static char namebuff[4096];
-
- addfn(fn, len, arg) char *fn; int len, arg; {
- int rslt;
- while (namebuff[bfptr++] = *fn++) ;
- rslt = 0;
- /********************************************************************/
- /* we want to pass this to be called from Modula-2, which doesn't */
- /* expect to have to unwind the stack: this is horrible. */
- /********************************************************************/
- asm { MOVD rslt, 0; EXIT #0; RXP #12; }
- }
-
- static int
- addfn(fn, len, arg) char *fn; int len, arg; {
- #ifdef ANSI
- while ( (namebuff[bfptr++] = *fn++) != '\0' ) ;
- #else
- while (namebuff[bfptr++] = *fn++) ;
- #endif
- return 0;
- }
-
- extern int Expand() asm;
-
- int
- zxpand(fn) char *fn; {
- bfptr = 0;
- countwild = Expand(fn, strlen(fn),
- &addfn, /* state arg = */ 42,
- /* target is dir = false */ 0);
- namebuff[bfptr] = '\0';
- bfptr = 0;
- return(countwild);
- }
-
- /**************************************************************************/
- /* Z N E X T -- Get name of next file from list created by zxpand(). */
- /* */
- /* Returns >0 if there's another file, with its name copied into the */
- /* arg string, or 0 if no more files in list. */
- /**************************************************************************/
-
- #ifdef ANSI
- int
- #endif
- znext(fn) char *fn; {
- #ifndef ANSI
- int i = 0;
- #endif
- char *thisone;
- if (countwild-- > 0) {
- if (namebuff[bfptr] == '\0') {
- printf("Internal error: eos in znext\n"); return(0);
- }
- thisone = &namebuff[bfptr];
- while (namebuff[bfptr++]) ;
- strcpy(fn, thisone);
- return(1);
- }
- else return(0);
- }
- #endif
-
-
- #ifdef ARTHUR
-
-
- #define MAXWLD 50 /* Maximum wildcard filenames */
- static int fcount; /* Number of files in wild group */
- static char *mtchs[MAXWLD], /* Matches found for filename */
- **mtchptr; /* Pointer to current match */
-
- int
- zxpand(fn) char *fn; {
- extern int fgen( char *, char *[], int );
-
- fcount = fgen(fn,mtchs,MAXWLD); /* Look up the file. */
- if (fcount > 0) {
- mtchptr = mtchs; /* Save pointer for next. */
- }
- debug(F111,"zxpand",mtchs[0],fcount);
- return(fcount);
- }
-
- /* Z N E X T -- Get name of next file from list created by zxpand(). */
- /*
- Returns >0 if there's another file, with its name copied into the arg string,
- or 0 if no more files in list.
- */
- int
- znext(fn) char *fn; {
- if (fcount-- > 0) strcpy(fn,*mtchptr++);
- else *fn = '\0';
- debug(F111,"znext",fn,fcount+1);
- return(fcount+1);
- }
-
- #endif
-
-
- /*******************************************************/
- /* Z N E W N -- Make a new name for the given file */
- /*******************************************************/
-
- #ifdef ANSI
- void
- #endif
- znewn(fn,s) char *fn, **s; {
- static char buf[256];
- int i = 0;
- #ifdef ANSI
- while ( (buf[i] = fn[i]) != '\0' ) i++;
- #else
- while (buf[i] = fn[i]) i++;
- #endif
- *s = buf;
- }
-
- /* Directory Functions for Unix, written by Jeff Damens, CUCCA, 1984. */
-
- /*
- * The path structure is used to represent the name to match.
- * Each slash-separated segment of the name is kept in one
- * such structure, and they are linked together, to make
- * traversing the name easier.
- */
-
- struct path {
- char npart[MAXNAMLEN]; /* name part of path segment */
- struct path *fwd; /* forward ptr */
- };
-
- #define SSPACE 2000 /* size of string-generating buffer */
- static char sspace[SSPACE]; /* buffer to generate names in */
- static char *freeptr,**resptr; /* copies of caller's arguments */
- static int remlen; /* remaining length in caller's array*/
- static int numfnd; /* number of matches found */
- static char nambuf[MAXNAMLEN+1]; /* Buffer for a filename */
-
- extern void traverse( struct path *, char *, char *);
- extern void addresult( char * );
- int iswild( char * );
- extern int match( char *, char * );
-
- /*
- * splitpath:
- * takes a string and splits the slash-separated portions into
- * a list of path structures. Returns the head of the list. The
- * structures are allocated by malloc, so they must be freed.
- * Splitpath is used internally by the filename generator.
- *
- * Input: A string.
- * Returns: A linked list of the slash-separated segments of the input.
- */
-
- struct path *
- splitpath(p)
- char *p;
- {
- struct path *head,*cur,*prv;
- int i;
- head = prv = NULL;
- /* if (*p == '$') p++;*/ /* skip leading slash */
- /* if (*p == ':') p+=2;*/ /* skip drive spec */
- while (*p != '\0')
- {
- cur = (struct path *) malloc(sizeof (struct path));
- debug(F101,"splitpath malloc","",(int)cur);
- if (cur == NULL) fatal("malloc fails in splitpath()");
- cur -> fwd = NULL;
- if (head == NULL) head = cur;
- else prv -> fwd = cur; /* link into chain */
- prv = cur;
- for (i=0; i < MAXNAMLEN && *p != '.' && *p != '\0'; i++)
- cur -> npart[i] = *p++;
- cur -> npart[i] = '\0'; /* end this segment */
- if (i >= MAXNAMLEN) while (*p != '.' && *p != '\0') p++;
- if (*p == '.') p++;
- }
- return(head);
- }
-
- /*
- * fgen:
- * This is the actual name generator. It is passed a string,
- * possibly containing wildcards, and an array of character pointers.
- * It finds all the matching filenames and stores them into the array.
- * The returned strings are allocated from a static buffer local to
- * this module (so the caller doesn't have to worry about deallocating
- * them); this means that successive calls to fgen will wipe out
- * the results of previous calls. This isn't a problem here
- * because we process one wildcard string at a time.
- *
- * Input: a wildcard string, an array to write names to, the
- * length of the array.
- * Returns: the number of matches. The array is filled with filenames
- * that matched the pattern. If there wasn't enough room in the
- * array, -1 is returned.
- * By: Jeff Damens, CUCCA, 1984.
- */
-
- int
- fgen(pat,resarry,len)
- char *pat,*resarry[];
- int len;
- {
- struct path *head;
- char scratch[100],*sptr;
-
- head = splitpath(pat);
-
- if ( *pat == '.' )
- {
- scratch[0] = '.';
- sptr = scratch+1;
- }
- else
- {
- /* strcpy(scratch,"");*/
- scratch[0] = '\0';
- sptr = scratch/*+2*/;
- } /* init buffer correctly */
- numfnd = 0; /* none found yet */
- freeptr = sspace; /* this is where matches are copied */
- resptr = resarry; /* static copies of these so*/
- remlen = len; /* recursive calls can alter them */
- traverse(head,scratch,sptr); /* go walk the directory tree */
- for (; head != NULL; head = head -> fwd)
- free(head); /* return the path segments */
- return(numfnd); /* and return the number of matches */
- }
-
- /* traverse:
- * Walks the directory tree looking for matches to its arguments.
- * The algorithm is, briefly:
- * If the current pattern segment contains no wildcards, that
- * segment is added to what we already have. If the name so far
- * exists, we call ourselves recursively with the next segment
- * in the pattern string; otherwise, we just return.
- *
- * If the current pattern segment contains wildcards, we open the name
- * we've accumulated so far (assuming it is really a directory), then read
- * each filename in it, and, if it matches the wildcard pattern segment, add
- * that filename to what we have so far and call ourselves recursively on the
- * next segment.
- *
- * Finally, when no more pattern segments remain, we add what's accumulated
- * so far to the result array and increment the number of matches.
- *
- * Input: a pattern path list (as generated by splitpath), a string
- * pointer that points to what we've traversed so far (this
- * can be initialized to "/" to start the search at the root
- * directory, or to "./" to start the search at the current
- * directory), and a string pointer to the end of the string
- * in the previous argument.
- * Returns: nothing.
- */
-
- void
- traverse(pl,sofar,endcur)
- struct path *pl;
- char *sofar,*endcur;
- {
- DIR *fd;
- struct dirent dir_entry;
- struct dirent *dirbuf = &dir_entry;
-
- struct FileData fileinfo;
- struct BTim timeinfo;
- int rc;
- int stamped;
-
- if (pl == NULL)
- {
- *--endcur = '\0'; /* end string, overwrite trailing / */
- addresult(sofar);
- return;
- }
-
- if (!iswild(pl -> npart))
- {
- strcpy(endcur,pl -> npart);
- endcur += strlen(pl -> npart);
- *endcur = '\0'; /* end current string */
- /* if (stat(sofar,&statbuf) == 0) */ /* if current piece exists */
- rc = GetFileInformation(&fileinfo, &timeinfo, sofar, strlen(sofar));
- if( rc >= 0 ) /* if current piece exists */
- {
- *endcur++ = '.'; /* add slash to end */
- *endcur = '\0'; /* and end the string */
- traverse(pl -> fwd,sofar,endcur);
- }
- return;
- }
-
- /* segment contains wildcards, have to search directory */
-
- *endcur = '\0'; /* end current string */
- if( *(endcur-1) == '.' )
- {
- /* Stamp on trailing . */
- *--endcur = '\0';
- stamped = 1;
- }
- else
- stamped = 0;
- /* if (stat(sofar,&statbuf) == -1) return;*/ /* doesn't exist, forget it */
- /* if ((statbuf.st_mode & S_IFDIR) == 0) return;*/ /* not a directory, skip */
-
- if( sofar[0] != '\0' )
- {
- /* cwd is represented as a NULL string!! */
- rc = GetFileInformation(&fileinfo, &timeinfo, sofar, strlen(sofar));
- if( rc == -1 ) return; /* doesn't exist, forget it */
- if( rc != 2 ) return; /* not a directory, skip */
- }
-
- if ((fd = opendir(sofar)) == NULL) return; /* can't open, forget it */
-
- if( stamped != 0 )
- {
- *endcur++ = '.';
- *endcur = '\0';
- }
-
- while ( (dirbuf = readdir(fd)) != NULL )
- {
- strncpy(nambuf,dirbuf->d_name,MAXNAMLEN); /* Get a null terminated copy!!! */
- nambuf[MAXNAMLEN] = '\0';
- /* if (dirbuf->d_ino != 0 && match(pl -> npart,nambuf)) {*/
- if ( match(pl -> npart,nambuf)) {
- char *eos;
- strcpy(endcur,nambuf);
- eos = endcur + strlen(nambuf);
- *eos = '.'; /* end this segment */
- traverse(pl -> fwd,sofar,eos+1);
- }
- }
-
- closedir(fd);
- }
-
- /*
- * addresult:
- * Adds a result string to the result array. Increments the number
- * of matches found, copies the found string into our string
- * buffer, and puts a pointer to the buffer into the caller's result
- * array. Our free buffer pointer is updated. If there is no
- * more room in the caller's array, the number of matches is set to -1.
- * Input: a result string.
- * Returns: nothing.
- */
-
- void
- addresult(str)
- char *str;
- {
- int l;
- if (strncmp(str,"./",2) == 0) str += 2;
- if (--remlen < 0) {
- numfnd = -1;
- return;
- }
- l = strlen(str) + 1; /* size this will take up */
- if ((freeptr + l) > &sspace[SSPACE]) {
- numfnd = -1; /* do not record if not enough space */
- return;
- }
- strcpy(freeptr,str);
- *resptr++ = freeptr;
- freeptr += l;
- numfnd++;
- }
-
- int
- iswild(str)
- char *str;
- {
- char c;
- while ((c = *str++) != '\0')
- if (c == '*' || c == '@') return(1);
- return(0);
- }
-
- /*
- * match:
- * pattern matcher. Takes a string and a pattern possibly containing
- * the wildcard characters '*' and '@'. Returns true if the pattern
- * matches the string, false otherwise.
- * by: Jeff Damens, CUCCA
- *
- * Input: a string and a wildcard pattern.
- * Returns: 1 if match, 0 if no match.
- */
-
-
- int
- match(pattern,string) char *pattern,*string; {
- char *psave,*ssave; /* back up pointers for failure */
- psave = ssave = NULL;
- while (1) {
- for (; *pattern == *string; pattern++,string++) /* skip first */
- if (*string == '\0') return(1); /* end of strings, succeed */
- if (*string != '\0' && *pattern == '@') {
- pattern++; /* '@', let it match */
- string++;
- } else if (*pattern == '*') { /* '*' ... */
- psave = ++pattern; /* remember where we saw it */
- ssave = string; /* let it match 0 chars */
- } else if (ssave != NULL && *ssave != '\0') { /* if not at end */
- /* ...have seen a star */
- string = ++ssave; /* skip 1 char from string */
- pattern = psave; /* and back up pattern */
- } else return(0); /* otherwise just fail */
- }
- }
-